﻿
namespace BJYJ_Admin.Application.System.Services.User;

[ApiDescriptionSettings("System")]
public class SysAreaService : IDynamicApiController, ITransient
{
    public readonly ISqlSugarClient _db;
    public SysAreaService(ISqlSugarClient db)
    {
        _db = db;
    }
    /// <summary>
    ///  获取区划列表                      
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取区划列表")]
    public virtual async Task<PageResult<AreaListOutDto>> GetAreaList([FromQuery] AreaSearchDto input)
    {
        RefAsync<int> totalCount = 0;
        var areaQuery = _db.Queryable<SYS_AREA>()
                    .WhereIF(!string.IsNullOrWhiteSpace(input.NAME), x => x.NAME.Contains(input.NAME))
                    .WhereIF(!string.IsNullOrWhiteSpace(input.CODE), x => x.CODE.Contains(input.CODE))
                    .WhereIF(input.STATUS.HasValue, x => x.STATUS == input.STATUS)
                    .WhereIF(input.DEPTH.HasValue, x => x.DEPTH == input.DEPTH)
                    .WhereIF(input.PID.HasValue, x => x.PID == input.PID)
                    .OrderBy(x => x.PID, OrderByType.Desc)
                    .OrderBy(x => x.ORDER_NUM, OrderByType.Asc)
                    .Select(outArea => new AreaListOutDto
                    {
                        ID = outArea.ID,
                        NAME = outArea.NAME,
                        CODE = outArea.CODE,
                        STATUS = outArea.STATUS,
                        PID = outArea.PID,
                        PARENT_PATH = outArea.PARENT_PATH,
                        DEPTH = outArea.DEPTH,
                        ORDER_NUM = outArea.ORDER_NUM,
                        ABBNAME = outArea.ABBNAME,
                        MEMO = outArea.MEMO

                    });
        // 执行分页查询
        var areaList = await areaQuery.ToPageListAsync(input.page, input.limit, totalCount);

        // 提取当前页所有区划ID
        var areaIds = areaList.Select(x => (int?)x.ID).ToList();

        // 批量查询哪些区划有子节点（使用聚合查询优化性能）
        var hasChildrenList = await _db.Queryable<SYS_AREA>()
            .Where(x => areaIds.Contains(x.PID))
            .GroupBy(x => x.PID)
            .Select(x => new { PID = x.PID })
            .ToListAsync();

        // 创建快速查找字典
        var hasChildrenDict = hasChildrenList.ToDictionary(x => x.PID, x => true);

        // 给每个角色设置HasChildren属性
        foreach (var area in areaList)
        {
            area.HASCHILDREN = hasChildrenDict.ContainsKey(area.ID);
        }
        return new PageResult<AreaListOutDto>
        {
            page = input.page,
            limit = input.limit,
            totalcount = totalCount,
            data = areaList
        };
    }
    /// <summary>
    /// 新增区划    
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("新增区划")]
    public virtual async Task AddArea(AreaInsertDto input)
    {
        var user = await _db.Queryable<SYS_AREA>().Where(x => x.CODE == input.CODE).FirstAsync();
        if (user != null)
            throw Oops.Oh("区划代码已存在！");
        var area = new SYS_AREA
        {
            NAME = input.NAME,
            CODE = input.CODE,
            STATUS = input.STATUS,
            PID = input.PID,
            PARENT_PATH = input.PARENT_PATH,
            ORDER_NUM = input.ORDER_NUM,
            DEPTH = input.DEPTH,
            ABBNAME = input.ABBNAME,
            MEMO = input.MEMO,
            CREATE_TIME = DateTime.Now,
            CREATE_BY = App.User?.FindFirstValue("ID")
        };
        await _db.Insertable(area).ExecuteCommandAsync();
    }
    /// <summary>
    /// 编辑区划
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("编辑区划")]
    public virtual async Task UpdateArea(SYS_AREA input)
    {
        input.UPDATE_TIME = DateTime.Now;
        input.UPDATE_BY = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable(input)
                .IgnoreColumns(u => new { u.CREATE_BY, u.CREATE_TIME })
                .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0002);
    }
    /// <summary>
    /// 删除区划
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除区划")]
    public virtual async Task DeleteAreaByID([FromQuery]AreaIDDto input)
    {
        // 开启事务处理
        var result = await _db.Ado.UseTranAsync(async () =>
        {
            // 1.查询要删除区划的完整路径
            var role = await _db.Queryable<SYS_AREA>().Where(x => x.ID == input.ID).FirstAsync();

            // 2.构建精确的路径匹配条件
            var currentAreaFullPath = $"{role.PARENT_PATH},{role.ID}";
            var pathPrefix = currentAreaFullPath + ",";  // 子区划路径前缀
            var directChildPath = currentAreaFullPath;   // 直接子节点路径

            // 3.查询要删除的子区划ID（精确匹配）
            var AreaIds = await _db.Queryable<SYS_AREA>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)  // 所有后代
                    || x.PARENT_PATH == directChildPath)          // 直接子节点
                .Select(x => (int?)x.ID)
                .ToListAsync();

            // 4.加入当前角色ID
            AreaIds.Add(input.ID);            

            // 5. 删除子区划（使用相同的路径条件）
            await _db.Deleteable<SYS_AREA>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)
                    || x.PARENT_PATH == directChildPath)
                .ExecuteCommandAsync();

            // 6. 删除当前区划
            await _db.Deleteable<SYS_AREA>()
                .Where(x => x.ID == input.ID)
                .ExecuteCommandAsync();

        });
        if (!result.IsSuccess)
            throw Oops.Oh(result.ErrorMessage);
    }

    /// <summary>
    /// 区划详情
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("区划详情")]
    public virtual async Task<SYS_AREA> GetAreaInfoByID(AreaIDDto input)
    {
        var user = await _db.Queryable<SYS_AREA>().Where(x => x.ID == input.ID).FirstAsync();
        return user;
    }

    /// <summary>
    /// 启用禁用区划
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("启用禁用区划")]
    public virtual async Task UpdateStatusByID(DeptStatusDto input)
    {
        var UserName = App.User?.FindFirstValue("USERNAME");
        var ID = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable<SYS_AREA>()
                                .SetColumns(it => it.STATUS == input.STATUS)
                                .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                                .SetColumns(it => it.UPDATE_BY == ID)
                                .Where(it => it.ID == input.ID)
                                .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0000);
    }

}

